home *** CD-ROM | disk | FTP | other *** search
/ Kit PC World De Ampliacion De Windows 95 / Kit PC World de ampliacion de Windows 95.iso / internet / sweeper / samples / olecon~1 / controls / webbit~1 / webbit~2.cpp < prev    next >
C/C++ Source or Header  |  1995-12-05  |  21KB  |  839 lines

  1. //=--------------------------------------------------------------------------=
  2. // WebBitmapCtl.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright  1995  Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. //
  13. //
  14. #include "IPServer.H"
  15.  
  16. #include "Guids.H"
  17. #include "LocalObj.H"
  18. #include "Util.H"
  19. #include "Globals.H"
  20. #include "Resource.H"
  21. #include "WebBitmapCtl.H"
  22.  
  23. // for ASSERT and FAIL
  24. //
  25. SZTHISFILE
  26.  
  27. WCHAR wszBitmap [] = L"Bitmap";
  28.  
  29.  
  30.  
  31.  
  32. //=--------------------------------------------------------------------------=
  33. // all the events in this control
  34. //
  35. // TODO: add events here ...
  36. //
  37.  
  38. //=--------------------------------------------------------------------------=
  39. // array describing all of our property pages.  these clsids are typically
  40. // in guids.h
  41. //
  42. // TODO: add any additional property page guids here ...
  43. //
  44. const GUID *rgWebBitmapPropPages [] = {
  45.     &CLSID_WebBitmapGeneralPage
  46. };
  47.  
  48. //=--------------------------------------------------------------------------=
  49. // Custum Verb information
  50. //
  51. // TODO: add any custom verbs here in an array, using the VERBINFO structure.
  52. //       then mark the controld def'n in WebBitmapCtl.H with
  53. //       this verb array
  54. //
  55.  
  56.  
  57. //=--------------------------------------------------------------------------=
  58. // CWebBitmapControl::Create
  59. //=--------------------------------------------------------------------------=
  60. // global static function that creates an instance of the control an returns
  61. // an IUnknown pointer for it.
  62. //
  63. // Parameters:
  64. //    IUnknown *        - [in] controlling unknown for aggregation
  65. //
  66. // Output:
  67. //    IUnknown *        - new object.
  68. //
  69. // Notes:
  70. //
  71. IUnknown *CWebBitmapControl::Create
  72. (
  73.     IUnknown *pUnkOuter
  74. )
  75. {
  76.     // make sure we return the private unknown so that we support aggegation
  77.     // correctly!
  78.     //
  79.     CWebBitmapControl *pNew = new CWebBitmapControl(pUnkOuter);
  80.     return pNew->PrivateUnknown();
  81. }
  82.  
  83. //=--------------------------------------------------------------------------=
  84. // CWebBitmapControl::CWebBitmapControl
  85. //=--------------------------------------------------------------------------=
  86. // "Being born is like being kidnapped.  And then sold into slavery."
  87. //    - andy warhol (1928 - 87)
  88. //
  89. // Parameters:
  90. //    IUnknown *        - [in]
  91. //
  92. // Notes:
  93. //
  94. #pragma warning(disable:4355)  // using 'this' in constructor
  95. CWebBitmapControl::CWebBitmapControl
  96. (
  97.     IUnknown *pUnkOuter
  98. )
  99. : CInternetControl(pUnkOuter, OBJECT_TYPE_CTLWEBBITMAP, (IDispatch *)this)
  100. {
  101.     m_bmpPath = 0;
  102.     m_dib = 0;
  103.     m_dibFile = 0;
  104.     m_state    = bdsNoBitsYet;
  105.  
  106. }
  107. #pragma warning(default:4355)  // using 'this' in constructor
  108.  
  109. //=--------------------------------------------------------------------------=
  110. // CWebBitmapControl::~CWebBitmapControl
  111. //=--------------------------------------------------------------------------=
  112. // "We all labour against our own cure, for death is the cure of all diseases"
  113. //    - Sir Thomas Browne (1605 - 82)
  114. //
  115. // Notes:
  116. //
  117. CWebBitmapControl::~CWebBitmapControl ()
  118. {
  119.     if(m_bmpPath)
  120.         delete m_bmpPath;
  121.     if( m_dibFile )
  122.         delete m_dibFile;
  123.     if( m_dib )
  124.         delete m_dib;
  125. }
  126.  
  127. //=--------------------------------------------------------------------------=
  128. // CWebBitmapControl:RegisterClassData
  129. //=--------------------------------------------------------------------------=
  130. // register the window class information for your control here.
  131. // this information will automatically get cleaned up for you on DLL shutdown.
  132. //
  133. // Output:
  134. //    BOOL            - FALSE means fatal error.
  135. //
  136. // Notes:
  137. //
  138. BOOL CWebBitmapControl::RegisterClassData()
  139. {
  140.     WNDCLASS wndclass;
  141.  
  142.     // TODO: register any additional information you find interesting here.
  143.     //       this method is only called once for each type of control
  144.     //
  145.     memset(&wndclass, 0, sizeof(WNDCLASS));
  146.     wndclass.style          = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC;
  147.     wndclass.lpfnWndProc    = COleControl::ControlWindowProc;
  148.     wndclass.hInstance      = g_hInstance;
  149.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  150.     wndclass.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  151.     wndclass.lpszClassName  = WNDCLASSNAMEOFCONTROL(OBJECT_TYPE_CTLWEBBITMAP);
  152.  
  153.     return RegisterClass(&wndclass);
  154. }
  155.  
  156. //=--------------------------------------------------------------------------=
  157. // CWebBitmapControl::BeforeCreateWindow
  158. //=--------------------------------------------------------------------------=
  159. // called just before the window is created.  Great place to set up the
  160. // window title, etc, so that they're passed in to the call to CreateWindowEx.
  161. // speeds things up slightly.
  162. //
  163. // Notes:
  164. //
  165. void CWebBitmapControl::BeforeCreateWindow()
  166. {
  167. }
  168.  
  169. void CWebBitmapControl::AfterCreateWindow()
  170. {
  171.     m_dc = ::GetDC(m_hwnd);
  172.     HPALETTE hpal = ::CreateHalftonePalette(m_dc);
  173.     ::SelectPalette(m_dc, hpal, FALSE);
  174.  
  175.     UpdateBitmap(); 
  176. }
  177.  
  178. //=--------------------------------------------------------------------------=
  179. // CWebBitmapControl::InternalQueryInterface
  180. //=--------------------------------------------------------------------------=
  181. // qi for things only we support.
  182. //
  183. // Parameters:
  184. // Parameters:
  185. //    REFIID        - [in]  interface they want
  186. //    void **       - [out] where they want to put the resulting object ptr.
  187. //
  188. // Output:
  189. //    HRESULT       - S_OK, E_NOINTERFACE
  190. //
  191. // Notes:
  192. //
  193. HRESULT CWebBitmapControl::InternalQueryInterface
  194. (
  195.     REFIID  riid,
  196.     void  **ppvObjOut
  197. )
  198. {
  199.     IUnknown *pUnk;
  200.  
  201.     *ppvObjOut = NULL;
  202.  
  203.     // TODO: if you want to support any additional interrfaces, then you should
  204.     // indicate that here.  never forget to call COleControl's version in the
  205.     // case where you don't support the given interface.
  206.     //
  207.     if (DO_GUIDS_MATCH(riid, IID_IWebBitmap)) {
  208.         pUnk = (IUnknown *)(IWebBitmap *)this;
  209.     } else{
  210.         return COleControl::InternalQueryInterface(riid, ppvObjOut);
  211.     }
  212.  
  213.     pUnk->AddRef();
  214.     *ppvObjOut = (void *)pUnk;
  215.     return S_OK;
  216. }
  217.  
  218. //=--------------------------------------------------------------------------=
  219. // CWebBitmapControl::LoadTextState
  220. //=--------------------------------------------------------------------------=
  221. // load in our text state for this control.
  222. //
  223. // Parameters:
  224. //    IPropertyBag *        - [in] property bag to read from
  225. //    IErrorLog *           - [in] errorlog object to use with proeprty bag
  226. //
  227. // Output:
  228. //    HRESULT
  229. //
  230. // Notes:
  231. //    - NOTE: if you have a binary object, then you should pass an unknown
  232. //      pointer to the property bag, and it will QI it for IPersistStream, and
  233. //      get said object to do a Load()
  234. //
  235. STDMETHODIMP CWebBitmapControl::LoadTextState
  236. (
  237.     IPropertyBag *pPropertyBag,
  238.     IErrorLog    *pErrorLog
  239. )
  240. {
  241.     VARIANT v;
  242.  
  243.     VariantInit(&v);
  244.  
  245.     v.vt = VT_BSTR;
  246.     v.bstrVal = NULL;
  247.  
  248.     HRESULT hr = S_OK;
  249.     // try to load in the property.  if we can't get it, then leave
  250.     // things at their default.
  251.     //
  252.     pPropertyBag->Read(::wszBitmap, &v, pErrorLog);
  253.     if (v.bstrVal) {
  254.         MAKE_ANSIPTR_FROMWIDE(psz, v.bstrVal);
  255.         hr = SetBmpPath(psz);
  256.         VariantClear(&v);
  257.     }
  258.  
  259.     return hr;
  260. }
  261.  
  262. //=--------------------------------------------------------------------------=
  263. // CWebBitmapControl::LoadBinaryState
  264. //=--------------------------------------------------------------------------=
  265. // loads in our binary state using streams.
  266. //
  267. // Parameters:
  268. //    IStream *            - [in] stream to write to.
  269. //
  270. // Output:
  271. //    HRESULT
  272. //
  273. // Notes:
  274. //
  275. const DWORD STREAMHDR_MAGIC = 12345678L;
  276.  
  277. STDMETHODIMP CWebBitmapControl::LoadBinaryState
  278. (
  279.     IStream *pStream
  280. )
  281. {
  282.     DWORD        sh;
  283.     HRESULT        hr;
  284.  
  285.     // first read in the streamhdr, and make sure we like what we're getting
  286.     //
  287.     hr = pStream->Read(&sh, sizeof(sh), NULL);
  288.     RETURN_ON_FAILURE(hr);
  289.  
  290.     // sanity check
  291.     //
  292.     if (sh != STREAMHDR_MAGIC )
  293.         return E_UNEXPECTED;
  294.  
  295.     return(SetBmpPath(pStream));
  296. }
  297.  
  298. //=--------------------------------------------------------------------------=
  299. // CWebBitmapControl::SaveTextState
  300. //=--------------------------------------------------------------------------=
  301. // saves out the text state for this control using a property bag.
  302. //
  303. // Parameters:
  304. //    IPropertyBag *        - [in] the property bag with which to work.
  305. //    BOOL                  - [in] if TRUE, then write out ALL properties, even
  306. //                            if they're their the default value ...
  307. //
  308. // Output:
  309. //    HRESULT
  310. //
  311. // Notes:
  312. //
  313. STDMETHODIMP CWebBitmapControl::SaveTextState
  314. (
  315.     IPropertyBag *pPropertyBag,
  316.     BOOL          fWriteDefaults
  317. )
  318. {
  319.     HRESULT hr;
  320.     VARIANT v;
  321.  
  322.     v.vt = VT_BSTR;
  323.     v.bstrVal = BSTRFROMANSI(m_bmpPath);
  324.     RETURN_ON_NULLALLOC(v.bstrVal);
  325.  
  326.     // this control currently only persists out the caption property
  327.     //
  328.     hr = pPropertyBag->Write(::wszBitmap, &v);
  329.     VariantClear(&v);
  330.     return hr;}
  331.  
  332. //=--------------------------------------------------------------------------=
  333. // CWebBitmapControl::SaveBinaryState
  334. //=--------------------------------------------------------------------------=
  335. // save out the binary state for this control, using the given IStream object.
  336. //
  337. // Parameters:
  338. //    IStream  *             - [in] save to which you should save.
  339. //
  340. // Output:
  341. //    HRESULT
  342. //
  343. // Notes:
  344. //    - it is important that you seek to the end of where you saved your
  345. //      properties when you're done with the IStream.
  346. //
  347. STDMETHODIMP CWebBitmapControl::SaveBinaryState
  348. (
  349.     IStream *pStream
  350. )
  351. {
  352.     DWORD sh = STREAMHDR_MAGIC;
  353.     HRESULT hr;
  354.  
  355.     // write out the stream hdr.
  356.     //
  357.     hr = pStream->Write(&sh, sizeof(sh), NULL);
  358.     RETURN_ON_FAILURE(hr);
  359.  
  360.     // write out he control state information
  361.     //
  362.  
  363.     DWORD dw = m_bmpPath ? lstrlen(m_bmpPath) : 0;
  364.  
  365.     hr = pStream->Write(&dw,sizeof(dw),0);
  366.     RETURN_ON_FAILURE(hr);
  367.  
  368.     if( dw )
  369.         hr = pStream->Write(m_bmpPath,dw+1,0);
  370.  
  371.     return hr;}
  372.  
  373.  
  374. //=--------------------------------------------------------------------------=
  375. // CWebBitmapControl::OnDraw
  376. //=--------------------------------------------------------------------------=
  377. // "I don't very much enjoy looking at paintings in general.  i know too
  378. //  much about them.  i take them apart."
  379. //    - georgia o'keeffe (1887-1986)
  380. //
  381. // Parameters:
  382. //    HDC                - [in]  HDC to draw to
  383. //    LPCRECTL           - [in]  rect we're drawing to
  384. //    LPCRECTL           - [in]  window extent and origin for meta-files
  385. //    HDC                - [in]  HIC for target device
  386. //
  387. // Output:
  388. //    HRESULT
  389. //
  390. // Notes:
  391. //
  392. HRESULT CWebBitmapControl::OnDraw
  393. (
  394.     HDC      hdcDraw,
  395.     LPCRECTL prcBounds,
  396.     LPCRECTL prcWBounds,
  397.     HDC      hicTargetDevice
  398. )
  399. {
  400.     if(m_dib) 
  401.     {
  402.         if( hdcDraw != m_dc )
  403.         {
  404.             HPALETTE hpal = ::CreateHalftonePalette(hdcDraw);
  405.             ::SelectPalette(hdcDraw, hpal, FALSE);
  406.         }
  407.  
  408.         ::RealizePalette(hdcDraw);
  409.  
  410.         m_dib->PaintTo(hdcDraw,prcBounds->left,prcBounds->top);
  411.     }
  412.     return S_OK;
  413. }
  414.  
  415. //=--------------------------------------------------------------------------=
  416. // CWebBitmapControl::OnProgress
  417. //=--------------------------------------------------------------------------=
  418. //
  419. // Parameters:
  420. //    DISPID    propId        - [in]  Same dispId that was passed into SetupDownload
  421. //    ULONG        progress    - [in]  Size downlaoded so far
  422. //    ULONG     themax        - [in]  Overall size of object being downloaded
  423. //    ULONG        statusFlag    - [in]  Flags according 
  424. //    LPCWSTR   statusStr    - [in]    Readable version of status
  425. //
  426. // Notes:
  427. //
  428. HRESULT CWebBitmapControl::OnProgress
  429. (
  430.     DISPID    propId, 
  431.     ULONG    progress, 
  432.     ULONG    themax, 
  433.     ULONG    statusFlag,
  434.     LPCWSTR    statusString
  435. )
  436. {
  437.     // TODO: put custom progress UI notification code here. The default action
  438.     //    (shown below) is to fire an OnProgress event to the host
  439.  
  440.     return(FireProgress(themax ? (progress * 100)/themax : 0));
  441. }
  442.  
  443.  
  444. //=--------------------------------------------------------------------------=
  445. // CWebBitmapControl::WindowProc
  446. //=--------------------------------------------------------------------------=
  447. // window procedure for this control.  nothing terribly exciting.
  448. //
  449. // Parameters:
  450. //     see win32sdk on window procs.
  451. //
  452. // Notes:
  453. //
  454. LRESULT CWebBitmapControl::WindowProc
  455. (
  456.     HWND   hwnd,
  457.     UINT   msg,
  458.     WPARAM wParam,
  459.     LPARAM lParam
  460. )
  461. {
  462.     // TODO: handle any messages here, like in a normal window
  463.     // proc.  note that for special keys, you'll want to override and
  464.     // implement OnSpecialKey.
  465.     //
  466.     return DefWindowProc(hwnd, msg, wParam, lParam);
  467. }
  468.  
  469. //=--------------------------------------------------------------------------=
  470. // CWebBitmapControl::AboutBox
  471. //=--------------------------------------------------------------------------=
  472. // prints up an about box.  fweeeee.
  473. //
  474. // Notes:
  475. //
  476. void CWebBitmapControl::AboutBox
  477. (
  478.     void
  479. )
  480. {
  481.     // TODO: Ideally, one would use DialogBox, and some sort of Dialog Box here if
  482.     // they wanted a slightly more interesting About Box ...  you should
  483.     // still call ModalDialog first, however.
  484.     //
  485.     ModalDialog(TRUE);
  486.     MessageBox(NULL, "This is My Control", "About WebBitmap", MB_OK | MB_TASKMODAL);
  487.     ModalDialog(FALSE);
  488. }
  489.  
  490. STDMETHODIMP CWebBitmapControl::get_ReadyState(long * thestate)
  491. {
  492.     CHECK_POINTER(thestate);
  493.     *thestate = m_readyState;
  494.     return(NOERROR);
  495. }
  496.  
  497. STDMETHODIMP  CWebBitmapControl::get_Bitmap(OLE_DATAPATH * path)
  498. {
  499.     CHECK_POINTER(path);
  500.  
  501.     // Actually we need to be accepting (happily IMoniker objects)
  502.  
  503.     path->vt = VT_BSTR;
  504.         
  505.     BSTR * pbstrPath = &path->bstrVal;
  506.     
  507.     *pbstrPath = (m_bmpPath && *m_bmpPath) ? BSTRFROMANSI(m_bmpPath) : SysAllocString(L"");
  508.  
  509.     return (*pbstrPath) ? S_OK : E_OUTOFMEMORY;
  510. }
  511.  
  512. STDMETHODIMP  CWebBitmapControl::put_Bitmap(OLE_DATAPATH path)
  513. {
  514.     // NOTE: We should reference and IMoniker*!!
  515.  
  516.     if( path.vt != VT_BSTR )
  517.         return(E_UNEXPECTED);
  518.  
  519.     BSTR & bstrPath = path.bstrVal;
  520.     // get an ANSI pointer, so we can stuff it in our local buffer for captions!
  521.     //
  522.  
  523.     MAKE_ANSIPTR_FROMWIDE(pszPath, bstrPath);
  524.  
  525.     HRESULT hr = SetBmpPath(pszPath);
  526.  
  527.     // update anybody who cares about property changes and mark ourselves
  528.     // as dirty
  529.     //
  530.     PropertyChanged(DISPID_BMPPATH);
  531.     m_fDirty = TRUE;
  532.  
  533.     return hr;
  534. }
  535.  
  536. STDMETHODIMP  CWebBitmapControl::Scramble()
  537. {
  538.     HRESULT hr;
  539.  
  540.     if( m_dib && (m_readyState == READYSTATE_COMPLETE) )
  541.     {
  542.         unsigned char * p = m_dib->Base();
  543.         DWORD            dw = m_dib->ImageSize();
  544.  
  545.         for( DWORD i = 0; i < dw; i+=3,p+=3 )
  546.             *p ^= 0x55;
  547.  
  548.         InvalidateControl(0);
  549.  
  550.         hr = S_OK;
  551.     }
  552.     else
  553.     {
  554.         hr = E_FAIL; // E_PENDING;
  555.     }
  556.  
  557.  
  558.     return(hr);
  559. }
  560.  
  561. HRESULT CWebBitmapControl::SetBmpPath(const char *psz)
  562. {
  563.     // if it hasn't changed, don't waste any time.
  564.     //
  565.     if (psz && m_bmpPath )
  566.     {
  567.         CHECK_POINTER(psz);
  568.         if( !lstrcmp(m_bmpPath, psz) )
  569.             return S_OK;
  570.     }
  571.  
  572.     if( m_bmpPath )
  573.         delete m_bmpPath;
  574.  
  575.     if(!psz)
  576.     {
  577.         m_bmpPath = 0;
  578.         return(S_OK);
  579.     }
  580.  
  581.     CHECK_POINTER(psz);
  582.  
  583.     if( !*psz )
  584.     {
  585.         m_bmpPath = 0;
  586.         return(S_OK);
  587.     }
  588.  
  589.     DWORD dw = lstrlen(psz);
  590.  
  591.     m_bmpPath = new char[dw + 1];
  592.  
  593.     if( !m_bmpPath )
  594.     {
  595.         FAIL("No memory");
  596.         return(E_OUTOFMEMORY);
  597.     }
  598.  
  599.     lstrcpy(m_bmpPath, psz);
  600.  
  601.     UpdateBitmap();
  602.  
  603.     return(S_OK);
  604. }
  605.  
  606. HRESULT CWebBitmapControl::SetBmpPath(IStream * strm)
  607. {
  608.     CHECK_POINTER(strm);
  609.  
  610.     char * tmp = 0;
  611.  
  612.     if( m_bmpPath )
  613.         delete m_bmpPath;
  614.  
  615.     DWORD    dw;
  616.     HRESULT hr = strm->Read(&dw,sizeof(dw),0);
  617.  
  618.     if( SUCCEEDED(hr) )
  619.     {
  620.         if( !dw )
  621.         {
  622.             hr = S_OK;
  623.         }
  624.         else
  625.         {
  626.             tmp = new char[dw+1];
  627.  
  628.             if( !tmp )
  629.             {
  630.                 FAIL("No memory");
  631.                 hr = E_OUTOFMEMORY;
  632.             }
  633.             else
  634.             {
  635.                 hr = strm->Read(tmp,dw+1,0);
  636.             }
  637.         }
  638.     }
  639.  
  640.     // if it hasn't changed, don't waste any time.
  641.     //
  642.     if ((!tmp && !m_bmpPath) || !lstrcmp(m_bmpPath, tmp))
  643.         return S_OK;
  644.  
  645.     if( m_bmpPath )
  646.         delete m_bmpPath;
  647.  
  648.     m_bmpPath = tmp;
  649.  
  650.     UpdateBitmap();
  651.  
  652.     return(hr);
  653. }
  654.  
  655. HRESULT CWebBitmapControl::UpdateBitmap()
  656. {
  657.     if( !m_hwnd )
  658.         return(S_OK);
  659.  
  660.     if( !m_bmpPath )
  661.         return(S_OK);
  662.  
  663.     FireReadyStateChange(READYSTATE_INTERACTIVE);
  664.  
  665.     return( SetupDownload(OLESTRFROMANSI(m_bmpPath),DISPID_BMPPATH) );
  666. }
  667.  
  668.  
  669. //=--------------------------------------------------------------------------=
  670. // CWebBitmapControl::OnData
  671. //=--------------------------------------------------------------------------=
  672. //
  673. // Parameters:
  674. //    DISPID    propId        - [in]  Same dispId that was passed into SetupDownload
  675. //    DWORD        grfBSCF        - [in]  Notification flags ("URL Moniker" specification)
  676. //    IStream *    strm        - [in]  Stream to read data from
  677. //    DWORD        dwSize        - [in]  Overall size available so far
  678. //
  679. //
  680. //    Notes:    This is the class that is monitering and interpreting the bits that
  681. //    are being downloaded. The methods in class inherited from IBindStatusCallback
  682. //    are only called during 'DispatchMessage' calls from the main applications loop.
  683. //    This impelmentation maintains a state machine for the bits as they arrive:
  684. //
  685. //        Initial state:            No bits have been seen yet
  686. //
  687. //        Have BITMAPFILEHEADER    We now have this structure. At this point there is
  688. //                                enough information to calculate the following values:
  689. //                                    - The file is actually a Windows BMP file
  690. //                                    - The size of the entire image
  691. //                                    - This size of the BITMAPINFO structure
  692. //
  693. //        Have BITMAPINFO            We now have enough information to call 
  694. //                                CreateDibSection! That function will return a 
  695. //                                a buffer it allocated.
  696. //
  697. //        Getting BITS            At this point the bits are arriving and all we 
  698. //                                have to do is strm->Read the bits directly into
  699. //                                buffer returned from the step above and notify
  700. //                                our view sink that we need refreshing.
  701. //
  702. //        BITS are done            (nothing to do!?)
  703. //
  704. HRESULT CWebBitmapControl::OnData
  705. (
  706.     DISPID        propId,
  707.     DWORD        grfBSCF,
  708.     IStream *    strm,
  709.     DWORD        dwSize
  710. )
  711. {
  712.     HRESULT        hr        = NOERROR;
  713.  
  714.     switch(m_state)
  715.     {
  716.         case bdsNoBitsYet:
  717.             {
  718.                 if( dwSize >= sizeof(BITMAPFILEHEADER) )
  719.                 {
  720.                     if( m_dibFile )
  721.                         delete m_dibFile;
  722.  
  723.                     m_dibFile = new CDibFile;
  724.  
  725.                     if( !m_dibFile )
  726.                     {
  727.                         hr = E_OUTOFMEMORY;
  728.                         break;
  729.                     }
  730.  
  731.                     hr = m_dibFile->GetFileHeader(strm);
  732.  
  733.                     if( FAILED(hr) )
  734.                         break;
  735.  
  736.                     m_state = bdsGotFileHeader;
  737.  
  738.                     // now FALL THRU!
  739.                 }
  740.                 else
  741.                 {
  742.                     break;
  743.                 }
  744.             }
  745.         
  746.         case bdsGotFileHeader:
  747.             {
  748.                 if( dwSize >= (m_dibFile->HeaderSize() + sizeof(BITMAPFILEHEADER)) )
  749.                 {
  750.                     if( m_dibFile )
  751.                         hr = m_dibFile->GetInfoHeader(strm);
  752.                     else
  753.                         hr = E_OUTOFMEMORY;
  754.  
  755.                     if( FAILED(hr) )
  756.                         break;
  757.  
  758.                     if( m_dib )
  759.                         delete m_dib;
  760.  
  761.                     m_dib = new CDibSection;
  762.  
  763.                     if( !m_dib )
  764.                     {
  765.                         hr = E_OUTOFMEMORY;
  766.                         break;
  767.                     }
  768.  
  769.                     m_dib->Setup(m_dc);
  770.  
  771.                     hr = m_dib->Create(*m_dibFile);
  772.  
  773.                     if( FAILED(hr) )
  774.                         break;
  775.  
  776.                     m_dib->ImageSize( m_dibFile->CalcImageSize() );
  777.                     m_state = bdsGotBitmapInfo;
  778.  
  779.                     // FALL THRU!
  780.  
  781.                 }
  782.                 else
  783.                 {
  784.                     break;
  785.                 }
  786.             }
  787.         
  788.         case bdsGotBitmapInfo:
  789.             {
  790.                 SIZEL    sz;
  791.                 m_dib->GetSize(sz);
  792.                 SetControlSize(&sz);
  793.  
  794.                 m_oldSize = (m_dibFile->HeaderSize() + sizeof(BITMAPFILEHEADER));
  795.  
  796.                 delete m_dibFile;
  797.                 m_dibFile = 0;
  798.  
  799.                 m_state = bdsGettingBits;
  800.  
  801.                 // FALL THRU
  802.             }
  803.  
  804.         case bdsGettingBits:
  805.             {
  806.                 if( dwSize > m_oldSize )
  807.                 {
  808.                     hr = m_dib->ReadFrom( strm, dwSize - m_oldSize );
  809.  
  810.                     if( FAILED(hr) )
  811.                         break;
  812.  
  813.                     ::RealizePalette(m_dc);
  814.  
  815.                     m_dib->PaintTo(m_dc);
  816.  
  817.                     m_oldSize = dwSize;
  818.                 }
  819.  
  820.                 if( grfBSCF & BSCF_LASTDATANOTIFICATION )
  821.                     m_state = bdsBitsAreDone;
  822.                 else
  823.                     break;
  824.             }
  825.         
  826.         case bdsBitsAreDone:
  827.             {
  828.                 m_state = bdsNoBitsYet;
  829.                 FireReadyStateChange(READYSTATE_COMPLETE);
  830.                 break;
  831.             }
  832.         
  833.     }
  834.  
  835.     return(hr);
  836. }
  837.  
  838.  
  839.